"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.GameRoom = exports.State = void 0;
const colyseus_1 = require("colyseus");
const schema_1 = require("@colyseus/schema");
const Utils_1 = require("../Utils");
const Setting_1 = require("../Setting");
const Player_1 = require("../Schema/Player");
// Our custom game state, an ArraySchema of type Player only at the moment
class State extends schema_1.Schema {
    constructor() {
        super(...arguments);
        this.players = new schema_1.MapSchema();
    }
}
__decorate([
    schema_1.type({ map: Player_1.Player })
], State.prototype, "players", void 0);
exports.State = State;
class GameRoom extends colyseus_1.Room {
    constructor() {
        super();
        this.maxClients = 8;
    }
    // When room is initialized
    onCreate(options) {
        // initialize empty room state
        this.setState(new State());
        this.onMessage("action", (client, message) => {
            // broadcast a message to all clients
            this.broadcast("action-taken", "an action has been taken!");
        });
        this.onMessage("fire", (client, data) => {
            // sends "fire" event to every client, except the one who triggered it.
            // this.broadcast("fire", message, {except: client});
            const player = this.state.players.get(client.sessionId);
            if (!player.active)
                return;
            let dir = player.dir;
            let b_x = player.x + player.w / 2;
            let b_y = player.y + player.h / 2;
            let offset = Math.max(player.w, player.h);
            // 修正发射位置位置
            switch (dir) {
                case 0:
                    b_y -= offset;
                    break;
                case 1:
                    b_x -= offset;
                    break;
                case 2:
                    b_y += offset;
                    break;
                case 3:
                    b_x += offset;
                    break;
            }
            // create a bullet
            let bullet = new Player_1.Bullet();
            bullet.x = b_x;
            bullet.y = b_y;
            player.bullets.push(bullet);
            let c = 0;
            let clientId = client.sessionId;
            let interval = setInterval(() => {
                if (c >= 60 || bullet.x < 0 || bullet.x > Setting_1.Setting.width || bullet.y < 0 || bullet.y > Setting_1.Setting.height) {
                    player.bullets.shift();
                    console.log(player.id, 'remove bullet', player.bullets.length);
                    clearInterval(interval);
                    return;
                }
                // 推演子弹飞行
                switch (dir) {
                    case 0:
                        bullet.y -= bullet.speed;
                        break;
                    case 1:
                        bullet.x -= bullet.speed;
                        break;
                    case 2:
                        bullet.y += bullet.speed;
                        break;
                    case 3:
                        bullet.x += bullet.speed;
                        break;
                }
                // simple碰撞检测
                let players = this.state.players;
                players.forEach((p, key) => {
                    // 针对非发射玩家
                    if (key !== clientId && p.active) {
                        let pc_x = p.x + p.w / 2;
                        let pc_y = p.y + p.h / 2;
                        if (Utils_1.simpleCollisionDetection(pc_x, pc_y, bullet.x, bullet.y, Math.max(p.w, p.h) / 2)) {
                            console.log('simple_detection', player.name, '->', p.name);
                            p.hp -= bullet.damage;
                            // 移除子弹
                            player.bullets.shift();
                            console.log(player.name, 'remove bullet', player.bullets.length);
                            // 死亡状态
                            if (p.hp <= 0) {
                                p.active = false;
                                console.log(player.name, 'death');
                            }
                            clearInterval(interval);
                        }
                    }
                });
                c++;
            }, 33);
        });
        // Called every time this room receives a "move" message
        this.onMessage("move", (client, data) => {
            const player = this.state.players.get(client.sessionId);
            player.dir = data.dir;
            // 触边掉头
            if (player.y < 10) {
                player.dir = 2;
            }
            else if (player.x < 10) {
                player.dir = 3;
            }
            else if (player.x > Setting_1.Setting.width - 60) {
                player.dir = 1;
            }
            else if (player.y > Setting_1.Setting.height - 60) {
                player.dir = 0;
            }
            // 前进
            switch (player.dir) {
                case 0:
                    player.y -= player.speed;
                    break;
                case 1:
                    player.x -= player.speed;
                    break;
                case 2:
                    player.y += player.speed;
                    break;
                case 3:
                    player.x += player.speed;
                    break;
            }
            console.log(client.sessionId + " at, x: " + player.x, "y: " + player.y);
        });
        this.onMessage("*", (client, type, message) => {
            // Triggers when any other type of message is sent,
            // excluding "action", which has its own specific handler defined above.
            console.log(client.sessionId, "sent", type, message);
        });
    }
    // Authorize client based on provided options before WebSocket handshake is complete
    // onAuth(client: Client, options: any, request: http.IncomingMessage) {
    // }
    // When client successfully join the room
    onJoin(client, options, auth) {
        let player = new Player_1.Player();
        player.color = Utils_1.randomColor();
        player.name = Utils_1.randomChineseName();
        player.id = client.sessionId;
        this.state.players.set(client.sessionId, player);
    }
    // When a client leaves the room
    onLeave(client, consented) {
        if (this.state.players.has(client.sessionId)) {
            this.state.players.delete(client.sessionId);
        }
    }
    // Cleanup callback, called after there are no more clients in the room. (see `autoDispose`)
    onDispose() {
    }
}
exports.GameRoom = GameRoom;
